package com.bdqn.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;

/**
 * SimpleBeanConvertor
 *
 * @author LILIBO
 * @since 2021-09-24
 */
public class SimpleBeanConvertor {

    /**
     * 将Map<String, String[]>类型的参数赋值给指定类型的JavaBean属性
     * SimpleBeanConvertor.convert(params, Person.class)
     *
     * @param params Map<String, String[]>参数
     * @param targetType 对应的类型
     * @param <T> 目标类型
     * @return 目标类型的实例对象
     */
    public static <T> T convert(Map<String, String[]> params, Class<T> targetType) throws IllegalAccessException, InstantiationException, InvocationTargetException, ParseException {
        // 如果参数对象为空，直接返回
        if (params == null) {
            return null;
        }
        // 通过反射，使用Class<T>构造一个对象
        T target = targetType.newInstance();
        // 获取Class<T>里面所有的public方法
        Method[] methods = targetType.getMethods();
        if (methods != null && methods.length > 0) {
            for (Method method : methods) {
                // 找到以set开头的方法
                if (method.getName().startsWith("set")) {
                    // 获取方法的参数列表
                    Class<?>[] args = method.getParameterTypes();
                    // 找到只有一个参数的方法
                    if (args.length == 1) {
                        // 获取对象属性的set方法，将request中的参数对应赋值给属性
                        // setName -> name
                        String paramName = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
                        // 查看所有参数的Map中是否存在key和对象的属性匹配的
                        if (params.containsKey(paramName)) {
                            try {
                                // 将HTTP请求中String类型的参数转换为对应实体类型
                                Object value = parseValue(params.get(paramName), args[0]);
                                // 使用目标对象target调用method方法，传递一个参数value
                                method.invoke(target, value);
                            } catch (ParseException e) {
                                System.out.println("参数转换错误：" + e.getMessage());
                                e.printStackTrace();
                                throw e;
                            }
                        } else if (Boolean.class == args[0] || boolean.class == args[0]) {
                            // 如果是boolean类型，不存在表示false
                            method.invoke(target, false);
                        }
                    }
                }
            }
        }
        return target;
    }

    /**
     * 将String[]类型或String[0]的参数值转换为相关属性的类型
     *
     * @param values 要转换的数据
     * @param type 对应的类型
     * @return
     */
    private static Object parseValue(String[] values, Class type) throws ParseException {
        if (values == null) {
            return null;
        }
        // 如果是数组直接返回
        if (type.isArray()) {
            return values;
        }
        // 如果不是数组，直接取出下标为0的数据即可
        String value = values[0];
        if (String.class == type) {
            return value;
        }
        if (boolean.class == type || Boolean.class == type) {
            if ("".equals(value) || "false".equals(value)) {
                return false;
            }
            return true;
        }
        if (java.util.Date.class == type) {
            return new SimpleDateFormat("yyyy-MM-dd").parse(value);
        }
        if (char.class == type || Character.class == type) {
            return value.charAt(0);
        }
        if (int.class == type || Integer.class == type) {
            return Integer.valueOf(value);
        }
        if (byte.class == type || short.class == type || long.class == type || float.class == type || double.class == type) {
            try {
                // byte | Byte -> Byte
                type = Class.forName("java.lang." + type.getName().substring(0, 1).toUpperCase() + type.getName().substring(1));
                if (type.getName().startsWith("java.lang.") || type.getName().startsWith("java.math.")) {
                    try {
                        // long l = new Long("9"); // 9
                        // 获取参数类型的构造函数（带一个String参数）
                        return type.getConstructor(String.class).newInstance(value);
                    } catch (Exception e) {
                        throw new UnsupportedTypeException(e);
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
